﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace JustWPFControls.Controls
{

    [TemplatePart(Name = "PART_Popup", Type = typeof(Popup))]
    [TemplatePart(Name = "PART_DayList", Type = typeof(ListBox))]
    [TemplatePart(Name = "PART_Switch", Type = typeof(ToggleButton))]
    [TemplatePart(Name = "PART_Left", Type = typeof(JIcon))]
    [TemplatePart(Name = "PART_Right", Type = typeof(JIcon))]
    public class JDatePicker : Control
    {
        static JDatePicker()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(JDatePicker), new FrameworkPropertyMetadata(typeof(JDatePicker)));
        }

        private ListBox? _dayList;
        private ToggleButton? _switch;
        private Popup? _popup;
        private JIcon? _left;
        private JIcon? _right;

        public DateTime? SelectedDate
        {
            get { return (DateTime?)GetValue(SelectedDateProperty); }
            set { SetValue(SelectedDateProperty, value); }
        }
        public static readonly DependencyProperty SelectedDateProperty =
            DependencyProperty.Register("SelectedDate", typeof(DateTime?), typeof(JDatePicker), new PropertyMetadata(null, SelectedDateChangedHandler));

        private static void SelectedDateChangedHandler(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var jDatePicker = (JDatePicker)d;
            jDatePicker.RefreshSelectedItem();
        }

        internal void RefreshSelectedItem()
        {
            if (_dayList != null && _dayList.Items.Count > 0)
            {
                var item = _dayList.SelectedItem as ListBoxItem;
                if (item == null || ((DateTime)item.Content).Date != SelectedDate)
                {
                    if (SelectedDate.HasValue)
                    {
                        // 查找等于 selectDatetime 的项
                        var selectedItem = _dayList.Items.Cast<ListBoxItem>().FirstOrDefault(item => (DateTime)item.Content == SelectedDate.Value.Date);
                        if (selectedItem != default)
                        {
                            // 找到匹配的项，设置为选中
                            _dayList.SelectedItem = selectedItem;
                        }
                    }
                    else
                    {
                        _dayList.SelectedItem = null;
                    }
                }
            }
        }

        public DateTime CurrentDate
        {
            get { return (DateTime)GetValue(CurrentDateProperty); }
            set { SetValue(CurrentDateProperty, value); }
        }
        public static readonly DependencyProperty CurrentDateProperty =
            DependencyProperty.Register("CurrentDate", typeof(DateTime), typeof(JDatePicker), new PropertyMetadata(null));

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            _popup = GetTemplateChild("PART_Popup") as Popup;
            _dayList = GetTemplateChild("PART_DayList") as ListBox;
            _switch = GetTemplateChild("PART_Switch") as ToggleButton;
            _left = GetTemplateChild("PART_Left") as JIcon;
            _right = GetTemplateChild("PART_Right") as JIcon;
            if (_popup != null)
                _popup.Closed += PopupClosed;
            if (_switch != null)
                _switch.Click += SwichClick;
            if (_dayList != null)
                _dayList.MouseLeftButtonUp += DayListMouseLeftButtonUp;
           
            if (_left != null)
                _left.MouseLeftButtonDown += (s, e) => ChangeMonth(-1);
            if ( _right != null)
                _right.MouseLeftButtonDown += (s, e) => ChangeMonth(1);
        }

        private void DayListMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (_dayList!.SelectedItem is ListBoxItem item)
            {
                SelectedDate = (DateTime)item!.Content;
                _popup!.IsOpen = false;
            }
        }

        private void PopupClosed(object? sender, EventArgs e)
        {
            if (!IsMouseOver)
            {
                _switch!.IsChecked = false;
            }
        }

        private void ChangeMonth(int day)
        {
            if (_popup!.IsOpen)
            {
                GenerateCalendar(CurrentDate.AddMonths(day));
            }
        }

        private void SwichClick(object sender, RoutedEventArgs e)
        {
            if (_switch!.IsChecked == true)
            {
                _popup!.IsOpen = true;
                //刷新日期列表
                GenerateCalendar(SelectedDate ?? DateTime.Now);
            }
        }

        private void GenerateCalendar(DateTime current)
        {
            if (current.Month == CurrentDate.Month && current.Year == CurrentDate.Year) return;
            
            CurrentDate = current;
            //生成日期列表
            _dayList?.Items.Clear();
            DateTime firstDayOfMonth = new DateTime(current.Year, current.Month,1);
            DateTime lastDayOfMonth = firstDayOfMonth.AddMonths(1).AddDays(-1);

            firstDayOfMonth = (int)firstDayOfMonth.DayOfWeek==0 ? firstDayOfMonth.AddDays(-6)
                : firstDayOfMonth.AddDays(-((int)firstDayOfMonth.DayOfWeek -1));
            lastDayOfMonth = (int)lastDayOfMonth.DayOfWeek == 0 ? lastDayOfMonth 
                : lastDayOfMonth.AddDays((7 - (int)lastDayOfMonth.DayOfWeek));

            for (DateTime tempDate = firstDayOfMonth; tempDate <= lastDayOfMonth; tempDate = tempDate.AddDays(1))
            {
                ListBoxItem dayItem = new ListBoxItem();
                dayItem.Content = tempDate;
                if (tempDate.Date == DateTime.Now.Date)
                {
                    dayItem.Tag = true;
                }
                _dayList?.Items.Add(dayItem);
            }

            RefreshSelectedItem();
        }
    }
}
